package models

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"gitchina/kly_service/util"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const (
	MD5_Key  = "1234567890"
	SignType = "0"
	//MerchantId = "008310107420099"
)

var merchantId = "008310147890008"
var regUserUrl = "https://cashier.allinpay.com/usercenter/merchant/UserInfo/reg.do"
var queryUrl = "https://cashier.allinpay.com/gateway/index.do"

func InitAllInPay(runmode string) {
	if runmode == "dev" || runmode == "" {
		merchantId = "008310107420099"
		regUserUrl = "http://116.236.252.102:18085/usercenter/merchant/UserInfo/reg.do"
	}
}

type AllInPayRS struct {
	State       int     `json:"state"`
	PayAmount   float32 `pay_amount`
	UserId      string  `json:"allinpay_user_id"`
	ProductName string  `json:"product_name"`
	SignMsg     string  `json:"sign_msg"`
}

func IsAllInPaySucc(params url.Values) (string, bool) {
	return params.Get("errorCode"), params.Get("payResult") == "1"
}

func GetAndVerifyAllInPay(params url.Values) (payId, userId, payData string, amount float32, ok bool) {
	p := make([]string, 0)
	p = append(p, fmt.Sprintf("merchantId=%s", params.Get("merchantId")))
	p = append(p, fmt.Sprintf("version=%s", params.Get("version")))
	if params.Get("language") != "" {
		p = append(p, fmt.Sprintf("language=%s", params.Get("language")))
	}
	p = append(p, fmt.Sprintf("signType=%s", params.Get("signType")))
	p = append(p, fmt.Sprintf("payType=%s", params.Get("payType")))
	if params.Get("issuerId") != "" {
		p = append(p, fmt.Sprintf("issuerId=%s", params.Get("issuerId")))
	}
	p = append(p, fmt.Sprintf("paymentOrderId=%s", params.Get("paymentOrderId")))
	p = append(p, fmt.Sprintf("orderNo=%s", params.Get("orderNo")))
	p = append(p, fmt.Sprintf("orderDatetime=%s", params.Get("orderDatetime")))
	p = append(p, fmt.Sprintf("orderAmount=%s", params.Get("orderAmount")))
	p = append(p, fmt.Sprintf("payDatetime=%s", params.Get("payDatetime")))
	p = append(p, fmt.Sprintf("payAmount=%s", params.Get("payAmount")))
	p = append(p, fmt.Sprintf("ext1=%s", params.Get("ext1")))
	if params.Get("ext2") != "" {
		p = append(p, fmt.Sprintf("ext2=%s", params.Get("ext2")))
	}
	p = append(p, fmt.Sprintf("payResult=%s", params.Get("payResult")))
	p = append(p, fmt.Sprintf("returnDatetime=%s", params.Get("returnDatetime")))
	p = append(p, fmt.Sprintf("key=%s", MD5_Key))
	payId = params.Get("orderNo")
	userId = strings.Replace(params.Get("ext1"), "<USER>", "", -1)
	userId = strings.Replace(userId, "</USER>", "", -1)
	payData = strings.Join(p, "&")
	tmp, _ := strconv.ParseFloat(params.Get("payAmount"), 32)
	amount = float32(tmp)
	ok = strings.ToUpper(fmt.Sprintf("%x", md5.Sum([]byte(payData)))) == params.Get("signMsg")
	return
}

func get_allinpay_sign(payId, rcvUrl, orderTime, productName, userId string, orderAmount float32) string {
	return strings.ToUpper(fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%s&key=%s", strings.Join([]string{
		"inputCharset=1",
		fmt.Sprintf("receiveUrl=%s", rcvUrl),
		"version=v1.0",
		"signType=1",
		fmt.Sprintf("merchantId=%s", merchantId),
		fmt.Sprintf("orderNo=%s", payId),
		fmt.Sprintf("orderAmount=%v", orderAmount),
		"orderCurrency=156",
		fmt.Sprintf("orderDatetime=%s", orderTime),
		fmt.Sprintf("productName=%s", productName),
		fmt.Sprintf("ext1=<USER>%s</USER>", userId),
		"payType=33",
	}, "&"), MD5_Key)))))
}

func post_allinpay_query(payId, payCreateTime string) (result string, err error) {
	var signMsg string
	var resp *http.Response
	var body []byte
	//var result map[string]interface{}
	queryTime := time.Now().Format("20060102150405")
	signMsg = fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("merchantId=%s&version=v1.5&signType=%s&orderNo=%s&orderDatetime=%s&queryDatetime=%s&key=%s",
		merchantId, SignType, payId, payCreateTime, queryTime, MD5_Key))))
	vals := url.Values{"merchantId": {merchantId}, "version": {"v1.5"}, "signType": {SignType}, "orderNo": {payId}, "orderDatetime": {payCreateTime}, "queryDatetime": {queryTime}, "signMsg": {strings.ToUpper(signMsg)}}
	util.GetLogger().Info("allinpay-query-post:content:%v", vals)
	if resp, err = http.PostForm(queryUrl, vals); err == nil {
		defer resp.Body.Close()
		if body, err = ioutil.ReadAll(resp.Body); err == nil {
			result = string(body)
			util.GetLogger().Info("allinpay-query-post:result:%s", result)
		}
	}
	return
}

func register_allinpay_user(memberId string) (userId string, err error) {
	var signMsg string
	var resp *http.Response
	var body []byte
	var result map[string]interface{}
	signMsg = fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("&signType=%s&merchantId=%s&partnerUserId=%s&key=%s&", SignType, merchantId, memberId, MD5_Key))))
	vals := url.Values{"signType": {SignType}, "merchantId": {merchantId}, "partnerUserId": {memberId}, "signMsg": {strings.ToUpper(signMsg)}}
	if resp, err = http.PostForm(regUserUrl, vals); err == nil {
		defer resp.Body.Close()
		if body, err = ioutil.ReadAll(resp.Body); err == nil {
			fmt.Println(fmt.Sprintf("%v", string(body)))
			if err = json.Unmarshal(body, &result); err == nil {
				resultCode := fmt.Sprintf("%v", result["resultCode"])
				if resultCode == "0000" || resultCode == "0006" {
					userId = fmt.Sprintf("%v", result["userId"])
				} else {
					err = fmt.Errorf("invalid result code:%s", resultCode)
				}
			}
		}
	}
	return
}
